// 蓝牙工具类
import { dateUtils, hexUtils } from "./utils";

export const BluetoothUtils = {}

// 设置系统变量
BluetoothUtils.vuex_os = {};


BluetoothUtils.initOS = function (os) {
    BluetoothUtils.vuex_os = os;
}


BluetoothUtils.serviceId = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'; // 蓝牙模块指定service
BluetoothUtils.characteristic_Id_6E400002 = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E'; // 无R、W指令 01设备关机 02清除历史记录
BluetoothUtils.characteristic_Id_6E400003 = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E'; // Notification接口 、W指令 获取离线历史数据
BluetoothUtils.characteristic_Id_6E400004 = '6E400004-B5A3-F393-E0A9-E50E24DCCA9E'; // Read & Write(62A214AF) APP获取和设置设备的时间
BluetoothUtils.characteristic_Id_6E400005 = '6E400005-B5A3-F393-E0A9-E50E24DCCA9E'; // (核心 开始记录、停止记录数据) 获取和设置记录状态
BluetoothUtils.characteristic_Id_6E400006 = '6E400006-B5A3-F393-E0A9-E50E24DCCA9E'; // 获取和设置同步状态 (是否正在进行历史数据传输)
BluetoothUtils.characteristic_Id_6E400007 = '6E400007-B5A3-F393-E0A9-E50E24DCCA9E'; // 获取数据总数
BluetoothUtils.characteristic_Id_6E400008 = '6E400008-B5A3-F393-E0A9-E50E24DCCA9E'; // 设置sn码




BluetoothUtils.buffer00 = new Uint8Array([0x00]).buffer
BluetoothUtils.buffer01 = new Uint8Array([0x01]).buffer
BluetoothUtils.buffer02 = new Uint8Array([0x02]).buffer

BluetoothUtils.buffer81 = new Uint8Array([0x81]).buffer
BluetoothUtils.buffer82 = new Uint8Array([0x82]).buffer


// 异常处理
BluetoothUtils.getError = function (errorCode) {
    if (errorCode == 0) return "OK";
    if (errorCode == 10000) return "未初始化蓝牙适配器";
    if (errorCode == 10001) return "当前蓝牙适配器不可用";
    if (errorCode == 10002) return "没有找到指定设备";
    if (errorCode == 10003) return "连接失败";
    if (errorCode == 10004) return "没有找到指定服务";
    if (errorCode == 10005) return "没有找到指定特征值";
    if (errorCode == 10006) return "当前连接已断开";
    if (errorCode == 10007) return "当前特征值不支持此操作";
    if (errorCode == 10008) return "其余所有系统上报的异常";
    if (errorCode == 10009) return "Android 系统特有，系统版本低于 4.3 不支持 BLE";
    return "未知异常";
}

// 检查蓝牙连接状态
BluetoothUtils.checkBluetoothConnection = function (bluetooth) {
    if (!bluetooth) {
        console.error('蓝牙对象为空');
        return false;
    }
    if (!bluetooth.deviceId) {
        console.error('蓝牙设备ID为空');
        return false;
    }
    if (!bluetooth.isLink) {
        console.error('蓝牙未连接');
        return false;
    }
    return true;
}



// 获取sn码
BluetoothUtils.getSN = function (bluetooth) {
    console.log('获取蓝牙设备时间：')
    uni.readBLECharacteristicValue({
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        characteristicId: BluetoothUtils.characteristic_Id_6E400008,
        success(res) {
            console.log('读取SN成功', res);
            uni.onBLECharacteristicValueChange(function (characteristic) {

                // 转换为 Uint8Array
                let hex = hexUtils.arrayBufferToHex(characteristic);
                if (hex.length > 20) {

                    const uint8Array = new Uint8Array(characteristic.value);
                    console.log('uint8Array:', uint8Array);
                    let sn = hexUtils.decryptSN(uint8Array)

                    console.log(sn);
                    // let hex = hexUtils.arrayBufferToHex(characteristic);
                }
            });
        }, fail(err) {
            console.error(err)
        }
    });
}


// 写入sn码
BluetoothUtils.writeSN = function (bluetooth, sn) {
    console.log('写入sn码...')

    let buffer = hexUtils.encryptSN(sn);

    console.log('写入sn码 buffer:', buffer);

    uni.writeBLECharacteristicValue({
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        characteristicId: BluetoothUtils.characteristic_Id_6E400008,
        value: buffer.buffer,
        writeType: BluetoothUtils.vuex_os.osName == 'ios' ? 'write' : 'writeNoResponse',
        success(res) {
            console.log('写入sn码 success', res);
        },
        fail(err) {
            console.error('写入sn码 err', err);
        }
    });

    uni.onBLECharacteristicValueChange(function (characteristic) {
        let hex = hexUtils.arrayBufferToHex(characteristic);
        console.log('发送继续收集数据指令 hex:', hex);
    });

}


///////////////////////////////////////  ** 新增方法 end ** /////////////////////////////////////////////////////


/**
 * 发送校时指令
 */
BluetoothUtils.correctionTime = function (bluetooth) {
    if (!BluetoothUtils.checkBluetoothConnection(bluetooth)) {
        console.error('蓝牙连接状态检查失败，无法发送校时指令');
        return;
    }

    let time = new Date().getTime() / 1000;
    time = time.toString(16);
    time = time.substring(0, 8);
    let hexs = new Uint8Array(time.match(/[\da-f]{2}/gi).map(function (h) {
        return parseInt(h, 16)
    }))
    let buffer = hexs.buffer;
    uni.writeBLECharacteristicValue({
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        characteristicId: BluetoothUtils.characteristic_Id_6E400004,
        value: buffer,
        writeType: BluetoothUtils.vuex_os.osName == 'ios' ? "write" : "writeNoResponse",
        success(res) {
            console.log('发送校时指令 成功:', res)
        },
        fail(err) {
            console.error('发送校时指令 失败:', err)
        }
    })
}

/**
 * 获取蓝牙设备时间
 * @param deviceId
 */
BluetoothUtils.getTime = function (bluetooth) {
    if (!BluetoothUtils.checkBluetoothConnection(bluetooth)) {
        console.error('蓝牙连接状态检查失败，无法获取设备时间');
        return;
    }

    uni.readBLECharacteristicValue({
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        characteristicId: BluetoothUtils.characteristic_Id_6E400004,
        success(res) {
            console.log('读取', res);
            let ok = true
            uni.onBLECharacteristicValueChange(function (characteristic) {
                let hex = hexUtils.arrayBufferToHex(characteristic);
                if (ok) {
                    console.log("当前时间", parseInt(hex, 16));
                    console.log(dateUtils.convertUnixToTime(parseInt(hex, 16)));
                    ok = false
                }
            });
        }, fail(err) {
            console.error(err)
        }
    });
}

/**
 * 关机
 */
BluetoothUtils.shutdown = function (bluetooth) {
    let that = this;
    console.log('关机-->function')
    uni.writeBLECharacteristicValue({
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        characteristicId: BluetoothUtils.characteristic_Id_6E400002,
        value: BluetoothUtils.buffer01,
        writeType: BluetoothUtils.vuex_os.osName == 'ios' ? "write" : "writeNoResponse",
        success(res) {
            console.log('关机成功！', res)
            uni.showToast({
                title: '您的蓝牙设备关机成功！', duration: 2500
            });

            uni.closeBluetoothAdapter({
                success(res) {
                    console.log("closeBluetoothAdapter... 成功...")
                }, complete: (res) => {
                    console.log("closeBluetoothAdapter... 完成... complete");
                }
            })
        },
        fail(err) {
            console.error(err)
            uni.showToast({
                title: '关机失败！'
            });
        }
    })
}

/**
 * 断开蓝牙
 * @param deviceId
 */
BluetoothUtils.closeBLEConnection =
    function (bluetooth) {
        uni.closeBLEConnection({
            deviceId: bluetooth.deviceId,
            success(res) {
            },
            fail(err) {
                console.log(err);
            }
        });
    }


/////////////////////////////////////// 数据操作方法 ///////////////////////////////////////

/**
 * 清除历史记录
 * @param deviceId
 */
BluetoothUtils.clearData = function (bluetooth) {
    console.log('清除历史记录-->function')
    return new Promise(function (resolve, reject) {
        console.log("执行清除数据方法")
        uni.writeBLECharacteristicValue({
            deviceId: bluetooth.deviceId,
            serviceId: BluetoothUtils.serviceId,
            characteristicId: BluetoothUtils.characteristic_Id_6E400002,
            value: BluetoothUtils.buffer02,
            writeType: BluetoothUtils.vuex_os.osName == 'ios' ? "write" : "writeNoResponse",
            success(res) {
                console.log('清空数据成功！')
                resolve(true)
            },
            fail(err) {
                console.error(err)
                resolve(false)
            }
        })
        console.log("执行清除数据方法 ok")
    })
}


/**
 * 开始记录数据
 */
BluetoothUtils.startRecord = function (bluetooth) {
    if (!BluetoothUtils.checkBluetoothConnection(bluetooth)) {
        console.error('蓝牙连接状态检查失败，无法开始记录数据');
        return;
    }

    console.log('开始/继续记录数据-->function')
    uni.writeBLECharacteristicValue({
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        characteristicId: BluetoothUtils.characteristic_Id_6E400005,
        value: BluetoothUtils.buffer01,
        writeType: BluetoothUtils.vuex_os.osName == 'ios' ? 'write' : 'writeNoResponse',
        success(res) {
            console.log('开始/继续记录数据 success', res);
        },
        fail(err) {
            console.error('开始/继续记录数据 err', err);
        }
    });

    uni.onBLECharacteristicValueChange(function (characteristic) {
        let hex = hexUtils.arrayBufferToHex(characteristic);
        console.log('发送继续收集数据指令 hex:', hex);
    });
}

/**
 *
 * 0001 67f4fcaf 085f 082c
 * 停止记录数据
 * @param deviceId
 */
BluetoothUtils.stopRecord = function (bluetooth) {
    console.log('停止记录数据-->function')
    return new Promise(function (resolve, reject) {
        uni.writeBLECharacteristicValue({
            deviceId: bluetooth.deviceId,
            serviceId: BluetoothUtils.serviceId,
            characteristicId: BluetoothUtils.characteristic_Id_6E400005,
            value: BluetoothUtils.buffer00,
            writeType: BluetoothUtils.vuex_os.osName == 'ios' ? 'write' : 'writeNoResponse',
            success(res) {
                resolve(res)
                console.log('停止记录数据 success', res);
            },
            fail(err) {
                reject(err)
                console.error('停止记录数据 err', err);
            }
        });
    })
}


/**
 * 获取离线数据
 */
BluetoothUtils.getRealData = function (bluetooth, callback) {
    return new Promise(function (resolve, reject) {
        BluetoothUtils.stopRecord(bluetooth).then((res) => {
            console.log('调用停止命令成功...');
            resolve(res);
        }).catch((err) => {
            reject(err);
        })
    }).then((res) => {
        return new Promise(function (resolve, reject) {
            BluetoothUtils.getDataCount(bluetooth).then(numCount => {

                let arr = [];
                console.log('获取离线数据-->function')
                uni.writeBLECharacteristicValue({
                    deviceId: bluetooth.deviceId,
                    serviceId: BluetoothUtils.serviceId,
                    characteristicId: BluetoothUtils.characteristic_Id_6E400006,
                    value: BluetoothUtils.buffer01,
                    writeType: getApp().globalData.osName == 'ios' ? 'write' : 'writeNoResponse',
                    success(res) {
                        console.log('同步离线数据 success', res);
                    },
                    fail(err) {
                        reject(err)
                        console.error('同步离线数据 err', err);
                    }
                });

                let isOk = false;
                let isOver = false;
                let start = new Date().getTime()
                let interval = {}

                // 执行获取同步时间数据...
                uni.onBLECharacteristicValueChange(function (characteristic) {
                    let hex = hexUtils.arrayBufferToHex(characteristic);
                    if (hex.length > 15) {
                        arr.push(hex);
                        // console.log('hex:', hex, "hex:length: ", hex.length, ' 当前数组长度:', arr.length);
                        let length = arr.length

                        // 如果4.0模块 单独处理 4.0 模块是每一条数据传16条

                        let percent = Number(length / numCount * 100).toFixed(2);

                        // 重新计算获取百分比
                        if (bluetooth.deviceVersion === '4.0') {
                            percent = Number((length * 16) / numCount * 100).toFixed(2);
                        }

                        if (percent > 100) {
                            percent = 100;
                        }

                        // 调用回调函数 同步百分比
                        callback?.syncPercent(percent); // 直接调用

                        isOk = true;
                        isOver = true;
                    } else if (hex.length < 15) {
                        if (isOk && isOver) {
                            clearInterval(interval);
                            console.log('传输结束')
                            console.log("hex:length: ", hex.length, " hex:", hex, ' 当前数组长度:', arr.length);
                            let end = new Date().getTime()
                            console.log('总耗时', `${(end - start) / 1000}s`)
                            isOver = false;


                            // 蓝牙4.0 的数据需要单独处理 每一次传16条数据
                            if (bluetooth.deviceVersion === '4.0') {
                                let arrTemp = splitPackets(arr)
                                resolve(arrTemp);
                            } else {
                                resolve(arr);
                            }

                            function splitPackets(arr) {
                                return arr.flatMap(str => str.match(/.{1,16}/g) || []);
                            }
                        }
                    }
                });
            });
        });

    }).catch(res => {
        console.log(res);
    });

}


/**
 * 终止同步数据
 * @param deviceId
 */
BluetoothUtils.stopRealData = function (bluetooth) {
    console.log('获取离线数据-->function')
    uni.writeBLECharacteristicValue({
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        characteristicId: BluetoothUtils.characteristic_Id_6E400006,
        value: BluetoothUtils.buffer02,
        writeType: BluetoothUtils.vuex_os.osName == 'ios' ? 'write' : 'writeNoResponse',
        success(res) {
            console.log('终止同步离线数据 success', res);
        },
        fail(err) {
            console.error('终止同步离线数据 err', err);
        }
    });

    // 执行获取同步时间数据...
    uni.onBLECharacteristicValueChange(function (characteristic) {
        let hex = hexUtils.arrayBufferToHex(characteristic);
        console.log("hex:", hex);
    });
}

/**
 * 获取蓝牙数据总数
 * @param deviceId
 */
BluetoothUtils.getDataCount = function (bluetooth) {
    console.log('获取蓝牙数据总数-->function')

    return new Promise(function (resolve, reject) {
        uni.readBLECharacteristicValue({
            deviceId: bluetooth.deviceId,
            serviceId: BluetoothUtils.serviceId,
            characteristicId: BluetoothUtils.characteristic_Id_6E400007,
            success(res) {
                console.log('获取蓝牙数据总数 ok：', res);
            },
            fail(err) {
                reject(err);
                console.error(err)
            }
        });

        uni.onBLECharacteristicValueChange(function (characteristic) {
            let hex = hexUtils.arrayBufferToHex(characteristic);
            console.log("总数 监听 hex:", hex);
            // 蓝牙模块1.0
            if (bluetooth.deviceVersion === '1.0') {
                console.log("蓝牙模块1.0");
                let str = hex.slice(0, 4)
                if (hex.length == 8 && str == '0000') {
                    let str2 = hex.slice(4, 8)
                    let data = hexUtils.convertHexTo10(str2); // 电压值
                    console.log("总数:", data);
                    resolve(data);
                }
            }
            // 蓝牙模块2.0
            if (bluetooth.deviceVersion === '2.0' || bluetooth.deviceVersion === '2.5' || bluetooth.deviceVersion === '3.0') {
                if (hex.length === 4) {
                    console.log("蓝牙模块2.0");
                    let data = hexUtils.convertHexTo10(hex); // 电压值
                    console.log("总数:", data);
                    resolve(data);
                }
            }
            if (bluetooth.deviceVersion === '4.0') {
                if (hex.length === 4) {
                    console.log("蓝牙模块4.0");
                    let data = hexUtils.convertHexTo10(hex); // 电压值
                    console.log("总数:", data);
                    resolve(data);
                }
            }
        });
    })
}


/////////////////////////////////////// 查看蓝牙状态方法 ///////////////////////////////////////


/**
 * 当前蓝牙是否正在同步数据(历史数据)
 */
BluetoothUtils.isSynchronous = function (bluetooth) {
    console.log('当前蓝牙是否正在同步数据-->function')
    uni.readBLECharacteristicValue({
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        characteristicId: BluetoothUtils.characteristic_Id_6E400006,
        success(res) {
            console.log(res);
        }
    });

    uni.onBLECharacteristicValueChange(function (characteristic) {
        let hex = hexUtils.arrayBufferToHex(characteristic);
        console.log(hex)
        // if (hex.length === 2) console.log('获取当前数据数据状态：', hex, ' 长度：', hex.length)
        // 测试来做
    });
}


/**
 * 是否正在记录离线数据
 */
BluetoothUtils.isRecord = function (bluetooth) {
    console.log('是否正在记录离线数据 -->function');
    return new Promise(function (resolve, reject) {
        uni.readBLECharacteristicValue({
            deviceId: bluetooth.deviceId,
            serviceId: BluetoothUtils.serviceId,
            characteristicId: BluetoothUtils.characteristic_Id_6E400005,
            success(res) {
                console.log(res);
            }
        });

        uni.onBLECharacteristicValueChange(function (characteristic) {
            let hex = hexUtils.arrayBufferToHex(characteristic);
            console.log('hex:', hex)
            if (hex.length === 2) {
                console.log("蓝牙模块2.0");
                let data = hexUtils.convertHexTo10(hex); // 电压值
                console.log("总数:", data);
                if (hex === '00') {
                    resolve(false);
                } else if (hex === '01') {
                    resolve(true);
                }

            }
        });
    });
}

/**
 * 当前蓝牙是否正在同步数据(历史数据)
 */
BluetoothUtils.isSynchronous = function (bluetooth) {
    console.log('当前蓝牙是否正在同步数据-->function')
    uni.readBLECharacteristicValue({
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        characteristicId: BluetoothUtils.characteristic_Id_6E400006,
        success(res) {
            console.log(res);
        }
    });

    uni.onBLECharacteristicValueChange(function (characteristic) {
        let hex = hexUtils.arrayBufferToHex(characteristic);
        console.log(hex)
        // if (hex.length === 2) console.log('获取当前数据数据状态：', hex, ' 长度：', hex.length)
        // 测试来做
    });
}


//////////////////////// 蓝牙模块 自带方法 //////////////////////////

/**
 * 获取蓝牙设备所有服务(service)
 * @param deviceId
 */
BluetoothUtils.getBLEDevice = function (bluetooth) {
    uni.getBLEDeviceCharacteristics({
        // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
        deviceId: bluetooth.deviceId,
        serviceId: BluetoothUtils.serviceId,
        success(res) {
            console.log('device getBLEDeviceCharacteristics:', res.characteristics)
        }
    })
}

/**
 * 监听蓝牙设备改变事件
 * @param deviceId
 */
BluetoothUtils.onBLEChange = function () {
    uni.onBLECharacteristicValueChange(function (characteristic) {
        let hex = hexUtils.arrayBufferToHex(characteristic);
        let version = hex.length
        if (version === 8) {
            let hexData = hex.substring(0, 4);
            let data = hexUtils.convertHexTo10(hexData);
            let khwHex = hex.substring(4, 8);
            let voltage = hexUtils.convertHexTo10(khwHex);
            console.log('蓝牙1.0 data:', data, '电量：', voltage);
        }
        if (version === 12) {
            let hexData1 = hex.substring(0, 4);
            let hexData2 = hex.substring(4, 8);

            let data1 = hexUtils.convertHexTo10(hexData1);
            let data2 = hexUtils.convertHexTo10(hexData2);

            let khwHex = hex.substring(8, 12);
            let voltage = hexUtils.convertHexTo10(khwHex);

            console.log('蓝牙2.0 data1:', data1, 'data2:', data2, '电量：', voltage.toFixed(2))
        }
        if (version === 16) {
            // 0000 0b51 0000 0f8b
            // todo 后面需要添加区分是单环还是双环的！！！
            let hexData1 = hex.substring(0, 4); // data1
            let hexData2 = hex.substring(4, 8); // data2
            let hexData3 = hex.substring(8, 12); // 电压
            let khwHex = hex.substring(12, 16); // 电压

            let data1 = hexUtils.convertHexTo10(hexData1);
            let data2 = hexUtils.convertHexTo10(hexData2);
            let data3 = hexUtils.convertHexTo10(hexData3);

            let voltage = hexUtils.convertHexTo10(khwHex);

            voltage = hexUtils.calPercentage(voltage);

            console.log('蓝牙2.0 Pro data1:', data1, 'data2:', data2, 'data3:', data3, '电量：', voltage);
        }
    });
}


BluetoothUtils.closeBlueAdapter = function () {
    uni.closeBluetoothAdapter({
        success() {
            console.log("关闭蓝牙适配器成功")
        }
    })
}

/////////////////////////////// 电量计算 //////////////////////////////////


BluetoothUtils.getDataBuffer = function (data) {
    return new Uint8Array([data]).buffer
};

/**
 * 计算电量
 * @param volatage
 * @returns {number}
 */
// 计算设备电量
BluetoothUtils.calPercentage = function (volatage) {
    let VoltageTable = [4142.2, 4011.2, 3812.9, 3731.0, 3674.9, 3534.4, 3488.4, 3305.3];
    let PercentageTable = [100, 86, 72, 58, 43, 29, 15, 1];
    let length = VoltageTable.length;
    let i = 0;
    for (i = 0; i < length; i++) {
        if (volatage >= VoltageTable[i]) {
            break;
        }
    }
    if (i >= length) {
        return 0;
    }
    if (i == 0) {
        return 100;
    }
    return (volatage - VoltageTable[i]) / ((VoltageTable[i - 1] - VoltageTable[i]) / (PercentageTable[i - 1] - PercentageTable[i])) + PercentageTable[i];
}

/////////////////////////////// 电量计算 //////////////////////////////////
